home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / hardware / gm1507 / g_mouse.asm < prev    next >
Assembly Source File  |  1994-10-27  |  26KB  |  1,222 lines

  1. ; -----------------------------------------------------------------------------
  2. ; G_MOUSE.ASM  Graphical mouse pointer in 80x25 text modes on EGA/VGA.
  3. ;           For Pascal and C/C++, real mode only.
  4. ;
  5. ;                          g_Mouse Interface Version 1.42
  6. ;
  7. ;                         Copyright(c) 1993,94 by B-coolWare.
  8. ;                                 Written by Bobby Z.
  9. ;                         Portions written by D. Dokolin.
  10. ; -----------------------------------------------------------------------------
  11. ;                                     "Nice, nice. Not excellent, but nice..."
  12. ;
  13. ;                                (Mel Brooks)
  14. ;
  15. ; License.
  16. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  17. ;
  18. ;SOFTWARE STATUS:
  19. ;
  20. ;This software is copyrighted free one. This means that it is distributed
  21. ; free of charge and that you must keep copyright notice with it. Usually this
  22. ; also means that you cannot modify the code, but it is not the case with
  23. ; this one (see grant of license for details). Note that it is not public
  24. ; domain software, that is author reserves copyright for it as well as some
  25. ; other rights.
  26. ;
  27. ;GRANT OF LICENSE:
  28. ;
  29. ;You are hereby granted the right to use this software in either commercial
  30. ; or non-commercial products provided that you do not charge any extra fee
  31. ; for this code and that you keep copyright notice unchanged. 
  32. ;You are also granted the right to distribute this code freely in its original
  33. ; unmodified form provided that you do not charge any fee that exceed your
  34. ; expences from doing it. 
  35. ;You also may modify the code to add new features or eliminate bugs or
  36. ; incompatibilites you discovered and distribute modified code provided that
  37. ; you add a notice that the code was modified. If you do any modifications
  38. ; to the code, please send me modified version so that I'll be able to
  39. ; reflect changes in the next releases. Regardless of the extent of modifica-
  40. ; tions the code should remain free and will still copyright(c) by B-coolWare. 
  41. ;If you break any of the rules mentioned you'll be liable for violation of
  42. ; Russian Copyright Law in Computer Programs and Databases as well as other
  43. ; national or international laws and treaties. The parties that acquired this
  44. ; code from you will still have their rights as long as they comply with this
  45. ; license.
  46. ;
  47. ;DISCLAIMER:
  48. ;
  49. ;Author disclaims all warranties, whether express or implied, of code quality,
  50. ; reliability or fitness for a particular purpose. I can only guarantee that it
  51. ; will occupy disk space. Though this code was thoroughly tested, the possibi-
  52. ; lity of errors can't be eliminated. Do not blame me if something goes wrong -
  53. ; you were warned.
  54. ;
  55. ;AUTHOR'S LIABILITY:
  56. ;
  57. ;In case of taking damage due to use, misuse or inability to use, this code,
  58. ; whether it is physical damage to your hardware, loss of data or profits,
  59. ; or any similar damages author shall not be liable for it. The whole risk is
  60. ; with you.
  61. ;
  62. ;AUTHOR'S EXCLUSIVE RIGHTS:
  63. ;
  64. ;Author reserves the right to use this code in any commercial or non-
  65. ; commercial software of his own design, the right to change the code partially
  66. ; or in whole without notification to its users and the right to change its
  67. ; status (to shareware, for example).
  68. ;
  69. ;How to contact author:
  70. ;~~~~~~~~~~~~~~~~~~~~~~
  71. ;If you experiencing problems with this code or have any suggestions, bug
  72. ; fixes or just wanna chat, refer to the following addresses:
  73. ;
  74. ; e-mail (preferrable):
  75. ;
  76. ; 2:5028/52.6 (FIDOnet)
  77. ; bob@ymz.yaroslavl.su (internet)
  78. ;
  79. ; paper mail:
  80. ;
  81. ; 150031,
  82. ; 10/4/13 Dobrynina Str.,
  83. ; Yaroslavl, 
  84. ; Russia
  85. ;
  86. ; Vladimir M. Zakharychev (aka Bobby Z.)
  87. ;
  88. ; Letters both in Russian and in English are welcome. Please do not use any
  89. ; other language if you want to be answered. Letter bombs are always
  90. ; returned to sender... shhhh-boom-BANG! :)
  91. ;
  92. ; Thank you for your interest in B-coolWare products.
  93. ;
  94. ;------------------------------------------------------------------------------
  95. ; Note for TV users:
  96. ; You MUST CORRECT Views.WriteView's logic in part determining if mouse is
  97. ; inside the area that will be drawn over, because now mouse pointer will
  98. ; occupy 4 characters instead of 1 when using ordinary mouse pointer. You also
  99. ; should change ShowMouse and HideMouse methods to call gShowMouse and
  100. ; gHideMouse when graphical pointer is in use. You can do it by allocating a
  101. ; boolean flag that indicates which pointer is used and proceed accordingly.
  102. ; The other way is to call Intercept33 at program startup, which will catch
  103. ; some mouse driver's functions to operate properly with graphical pointer, and
  104. ; call Untercept33 before program stop.
  105. ; -----------------------------------------------------------------------------
  106. ;
  107. ; History:
  108. ;       25 Oct 1993  initial release
  109. ;       21 Jan 1994  added some improvements
  110. ;       08 Feb 1994  adopted for Turbo Vision (Real mode only)
  111. ;       14 Apr 1994  slightly optimized and commented
  112. ;       22 Aug 1994  some corrections made
  113. ;       25 Oct 1994  some more corrections made
  114.  
  115. ; This code needs Turbo Assembler 2.5 or above to be compiled.
  116.  
  117.     MODEL    TPASCAL    ; uncomment this to use with TP/BP
  118. ;    MODEL    LARGE,C    ; uncomment this to use with C/C++ compilers
  119. ;        ^^^^^ change to preferred memory model
  120.  
  121.     .CODE
  122.  
  123.     LOCALS        ; allow local symbols started with @@
  124.     JUMPS        ; smart jumps - no "jump out of range" errors
  125.  
  126. ; two special defines control the way this code is assembled:
  127. ;
  128. ; __use_286__  forces 286-specific instructions to be compiled in certain
  129. ;           places
  130. ; __use_386__  forces 386-specific instructions to be compiled in certain
  131. ;           places
  132. ;
  133.  
  134.  
  135. ifdef    __use_386__
  136.  ifndef __use_286__
  137.   __use_286__    equ    1
  138.  endif
  139.     .386
  140. endif
  141.  
  142. ifdef    __use_286__
  143.  ifndef __use_386__
  144.     .286
  145.  endif
  146. endif
  147.  
  148. _bp    EQU    <BYTE PTR>
  149. _wp    EQU    <WORD PTR>
  150.  
  151. load    MACRO    reg, Reference
  152.     mov    reg,offset Reference
  153.     ENDM
  154.  
  155. ldx    MACRO    Reference
  156.     load    dx,Reference
  157.     ENDM
  158.  
  159. lsi    MACRO    Reference
  160.     load    si,Reference
  161.     ENDM
  162.  
  163. ldi    MACRO    Reference
  164.     load    di,Reference
  165.     ENDM
  166.  
  167. callf    MACRO    Address
  168.     call    dword ptr Address
  169.     ENDM
  170.  
  171. clr    MACRO    reg
  172.     sub    reg,reg
  173.     ENDM
  174.  
  175. C1Code    EQU    0DEh ; '▐'
  176. C2Code    EQU    0DDh ; '▌'
  177. C3Code    EQU    0D7h ; '╫'
  178. C4Code    EQU    0D8h ; '╪'
  179.  
  180.     PUBLIC    gInitMouse, gShowMouse, gHideMouse, gMouseGotoXY, gDoneMouse
  181.     PUBLIC  gMouseWhereX, gMouseWhereY, gMouseActive
  182.  
  183.     PUBLIC  Intercept33, Untercept33
  184.  
  185.     PUBLIC    gMouseSetChars, gMouseGetChars
  186.  
  187. ; PUBLICs list by name and function as to appear in interface section:
  188. ;
  189. ; INIT/DEINIT FUNCTIONS
  190. ;
  191. ; procedure gInitMouse( doModeFlip : Boolean ); far;
  192. ; - initializes g_Mouse. doModeFlip controls whether we should program VGA for
  193. ;   8x16 character matrix size (allows smooth cursor movement).
  194. ;
  195. ; procedure gDoneMouse( doModeFlip : Boolean ); far;
  196. ; - deinitialize g_Mouse. Should be called prior to program exit if gInitMouse
  197. ;   was called. doModeFlip controls whether the effect of gInitMouse with
  198. ;   doModeFlip of TRUE should be undone.
  199. ;
  200. ; procedure gMouseSetChars( C1, C2, C3, C4 : Char ); far;
  201. ; - sets four characters that will be used to substitute mouse pointer on
  202. ;   screen.
  203. ;
  204. ; procedure gMouseGetChars( var C1, C2, C3, C4 : Char ); far;
  205. ; - returns current substitution character codes.
  206. ;
  207. ; LOW-LEVEL INTERFACE FUNCTIONS
  208. ;
  209. ; procedure gShowMouse; far;
  210. ; - analogue to ShowMouse. Displays mouse pointer on screen.
  211. ;
  212. ; procedure gHideMouse; far;
  213. ; - analogue to HideMouse. Hides mouse pointer off screen.
  214. ;
  215. ; procedure gMouseGotoXY( X, Y : Integer ); far;
  216. ; - sets new mouse pointer position.
  217. ;
  218. ; function gMouseWhereX : Integer;
  219. ; - returns current mouse X position (in terms of characters, not pixels).
  220. ;
  221. ; function gMouseWhereY : Integer;
  222. ; - returns current mouse Y position (in terms of characters, not pixels).
  223. ;
  224. ; function gMouseActive : Boolean;
  225. ; - returns TRUE if g_Mouse event handler is active.
  226. ;
  227. ; HIGH-LEVEL INTERFACE FUNCTIONS
  228. ;
  229. ; procedure Intercept33; far;
  230. ; - provides high-level interface to g_Mouse intercepting Mouse Services
  231. ;   Interrupt (INT 33h) eliminating need to call any of low-level interface
  232. ;   functions.
  233. ;
  234. ; procedure Untercept33; far;
  235. ; - undoes the effect of Intercept33.
  236. ;
  237. ; when using In(Un)tercept33 functions all mouse services works fine. Although
  238. ; if you do not use them, you may not use any of mouse services directly for
  239. ; it will crush g_Mouse system leading to unpredictable results. You may use
  240. ; only functions listed in low-level interface section to communicate with
  241. ; mouse if In(Un)tercept33 functions are not used. I suggest that you will use
  242. ; In(Un)tercept33 for your own convenience. Just call Intercept33 right on
  243. ; program startup just AFTER calling gInitMouse and call Untercept33 before
  244. ; program exit just before calling gDoneMouse. Intercept33 will not grab INT
  245. ; 33h vector if g_Mouse was not initialized due to any reason, whether you
  246. ; forgot to call gInitMouse or no EGA/VGA found on your system.
  247.  
  248. ; INTERNAL VARIABLES
  249.  
  250. OldHandler    DD    ?    ; old mouse handler
  251. OldEvents    DW    ?    ; old event mask
  252. Active        DB    0    ; is our handler activated
  253. MouseVisible    DB    0    ; is mouse cursor visible
  254. OldChars    DB    4 DUP(?); saved characters under mask
  255. OldPos        DW    ?    ; where they were
  256. CurX        DW    0    ; current X coord
  257. CurY        DW    0    ; current Y coord
  258. C1        DB    16 DUP(?); C1 character map
  259. C3        DB    16 DUP(?); C3 character map
  260. C2        DB    16 DUP(?); C2 character map
  261. C4        DB    16 DUP(?); C4 character map
  262. CharSize    DW    16    ; character size (may be changed by CheckVideo)
  263. XMin        DW    0    ; mouse window x min limit
  264. YMin        DW    0    ; mouse window y min limit
  265. XSize        DW    639    ; mouse window x max limit
  266. YSize        DW    394    ; display height in pixels (VGA initialized)
  267. YMax        DW    394    ; mouse window y max limit
  268. SaveBuffer    DW    32 DUP(?); maps of internal characters saved here
  269. C1C        DW    C1Code    ; four characters used to substitute the mouse
  270. C2C        DW    C2Code    ; pointer - you should not use these codes
  271. C3C        DW    C3Code    ; elsewhere in your user interface.
  272. C4C        DW    C4Code
  273.  
  274. ORMask:                ; mask to be ORed with character maps
  275.         DW     00000000B
  276.         DB    01000000B
  277.         DB    01100000B
  278.         DB    01110000B
  279.         DB    01111000B
  280.         DB    01111100B
  281.         DB    01111110B
  282.         DB    01111111B
  283.         DB    01111100B
  284.         DB    01001100B
  285.         DB    00001110B
  286.         DB    00000110B
  287.         DB    00000110B
  288.         DB    00000000B
  289.         DB    00000000B
  290.         DB    00000000B
  291.  
  292. ANDMask:            ; mask to be ANDed with character maps
  293.         DB    00111111B
  294.         DB    00011111B
  295.         DB    00001111B
  296.         DB    00000111B
  297.         DB    00000011B
  298.         DB    00000001B
  299.         DB    00000000B
  300.         DB    00000000B
  301.         DB    00000000B
  302.         DB    00000001B
  303.         DB    00100001B
  304.         DB    11110000B
  305.         DB    11110000B
  306.         DB    11110000B
  307.         DB    11111111B    ; two lines will still unchanged for
  308.         DB    11111111B    ; EGA 8x14 modes compatibility
  309.  
  310.  
  311. ; IMPLEMENTATION
  312.  
  313. gMouseHandler    PROC FAR
  314.     test    ax,1            ; we handle only movements
  315.     jz    @@1
  316.  
  317. ifdef    __use_286__
  318.     pusha
  319.     push    es ds
  320. else
  321.     push    ax bx si di es ds
  322. endif    
  323.     mov    al,cs:[MouseVisible]    ; save mouse state on stack
  324.     push    ax
  325.     call    gHideMouse        ; hide mouse if visible
  326.     call    GetNewPos        ; calculate new pointer position
  327.     pop    ax
  328.     or    al,al            ; was pointer visible?
  329.     jz    @@2            ; no, just update coordinates
  330.     call    gShowMouse        ; show mouse in new position
  331. @@2:
  332. ifdef    __use_286__
  333.     pop    ds es
  334.     popa
  335. else
  336.     pop    ds es di si bx ax
  337. endif
  338. @@1:
  339.     push    ax
  340.     mov    ax,cs:[CurY]        ; convert Y coordinate to represent
  341.     cwd                ; vertical position in universal pixels
  342.     div    cs:[CharSize]        ; that is this position divided by 8
  343. ifdef    __use_286__
  344.     shl    ax,3
  345. else
  346.     shl    ax,1            ; will give character position -
  347.     shl    ax,1            ; independent on character matrix size
  348.     shl    ax,1
  349. endif
  350.     mov    cx,cs:[CurX]        ; character matrix size by X is always
  351.     mov    dx,ax            ; 8, it need not be adjusted
  352.     and    cl,0F8h
  353.     and    dl,0F8h
  354.     pop    ax
  355.     and    ax,cs:[OldEvents]    ; leave only events they want
  356.     jz    @@Q            ; are there any events left?
  357.     push    ax            ; check if OldHandler points somewhere
  358.     mov    ax,_wp cs:[OldHandler]
  359.     or    ax,_wp cs:[OldHandler][2]
  360.     pop    ax
  361.     jz    @@Q            ; no handler defined
  362.     callf    cs:[OldHandler]        ; chain to old handler
  363. @@Q:
  364.     jmp    @@E
  365.     db    13,10,'g_Mouse Interface  Version 1.42 Copyright (c) 1993,94 by B-coolWare.',13,10
  366. @@E:
  367.     ret
  368.     ENDP
  369.  
  370.  
  371. gInitMouse    PROC FAR
  372. ; procedure gInitMouse; far;
  373. ; initializes mouse handler internal variables
  374. ARG    doModeFlip : BYTE
  375.  
  376.     call    checkVideo        ; check if this is EGA/VGA and we're in
  377.     jc    @@Q            ; right mode
  378.     mov    ax,3533h        ; check interrupt vector
  379.     int    21h
  380.     mov    ax,es
  381.     or    bx,ax
  382.     jz    @@Q
  383.     clr    ax            ; check if mouse support installed
  384.     int    33h
  385.     inc    ax            ; it will return 0FFFFh if installed,
  386.     jnz    @@Q            ; adding 1 will produce zero result
  387.     cmp    doModeFlip,1
  388.     jnz    @@noflip
  389.     call    mode8bpc
  390. @@noflip:
  391.     push    cs:C1C
  392.     push    cs:C2C
  393.     push    cs:C3C
  394.     push    cs:C4C
  395.     call    LoadChars        ; saving original character maps
  396.     push    ds             ; into SaveBuffer
  397.     push    cs cs
  398.     pop    ds es
  399.     lsi    C1
  400.     ldi    SaveBuffer
  401. ifdef    __use_386__
  402.     mov    cx,16
  403.     cld
  404.     rep    movsd
  405. else
  406.     mov    cx,32
  407.     cld
  408.     rep    movsw
  409. endif
  410.     pop    ds
  411.     mov    cs:[Active],1        ; we can operate
  412.     ldx    gMouseHandler
  413.     mov    cx,7Fh
  414.     mov    ax,14h            ; exchange event handlers
  415.     int    33h
  416.     mov    _wp cs:[OldHandler],dx
  417.     mov    _wp cs:[OldHandler][2],es
  418.     mov    _wp cs:[OldEvents],cx
  419. @@Q:
  420.     ret
  421.     ENDP
  422.  
  423.  
  424. gShowMouse    PROC FAR
  425. ; procedure gShowMouse; far;
  426. ; shows mouse pointer
  427.  
  428.     cmp    cs:[Active],0        ; are we operatable?
  429.     jz    @@Q
  430.     cmp    cs:[MouseVisible],1    ; is mouse already on screen?
  431.     jz    @@Q
  432.     push    ax si es ds
  433.     push    cs
  434.     pop    ds
  435.     call    computeOffset        ; compute offset in video buffer to
  436.     mov    OldPos,si        ; mouse pointer position
  437.     mov    ax,0B800h
  438.     mov    es,ax
  439.     mov    al,es:[si]        ; save characters currently there
  440.     mov    OldChars,al
  441.     mov    al,es:[si+2]
  442.     mov    OldChars[1],al
  443.     mov    al,es:[si+160]
  444.     mov    OldChars[2],al
  445.     mov    al,es:[si+162]
  446.     mov    OldChars[3],al
  447.     push    es si
  448.     call    UpdateChars        ; apply a mask on current chars
  449.     pop    si es
  450.     mov    al,_bp cs:[C1C]
  451.     mov    ah,_bp cs:[C3C]
  452.     mov    es:[si],al        ; and put new chars on screen
  453.     mov    es:[si+160],ah
  454.     cmp    cs:[CurX],632        ; right bound?
  455.     jae    @@10            ; yes - prevent wraparound
  456.     mov    al,_bp cs:[C2C]
  457.     mov    ah,_bp cs:[C4C]
  458.     mov    _bp es:[si+2],al
  459.     mov    _bp es:[si+162],ah
  460. @@10:
  461.     pop    ds es si ax
  462.     mov    cs:[MouseVisible],1
  463. @@Q:
  464.     ret
  465.     ENDP
  466.  
  467.  
  468. gHideMouse    PROC FAR
  469. ; procedure gHideMouse; far;
  470. ; hides mouse cursor
  471.  
  472.     cmp    cs:[Active],0
  473.     jz    @@Q
  474.     cmp    cs:[MouseVisible],0
  475.     jz    @@Q
  476.     push    ax ds es di cs
  477.     pop    ds
  478.     mov    di,OldPos
  479.     mov    ax,0B800h
  480.     mov    es,ax
  481.     mov    al,OldChars        ; put old characters back where
  482.     mov    es:[di],al        ; they were
  483.     mov    al,OldChars[1]
  484.     mov    es:[di+2],al
  485.     mov    al,OldChars[2]
  486.     mov    es:[di+160],al
  487.     mov    al,OldChars[3]
  488.     mov    es:[di+162],al
  489.     pop    di es ds ax
  490.     mov    cs:[MouseVisible],0
  491. @@Q:
  492.     ret
  493.     ENDP
  494.  
  495.  
  496. gMouseGotoXY    PROC FAR
  497. ; procedure gMouseGotoXY(X,Y : Integer); far;
  498. ; sets new mouse position to (X,Y) (character position, not pixel)
  499. ARG    X,Y
  500.  
  501.     cmp    cs:[Active],1
  502.     jnz    @@Q
  503. ifdef    __use_286__
  504.     pusha
  505.     push    es ds
  506. else
  507.     push    ax bx cx dx si di es ds
  508. endif
  509.     mov    al,cs:[MouseVisible]
  510.     push    ax
  511.     call    gHideMouse        ; hide mouse
  512.     mov    ax,X            ; compute pixel coordinates of
  513. ifdef    __use_286__
  514.     shl    ax,3
  515. else
  516.     shl    ax,1            ; mouse pointer hotspot
  517.     shl    ax,1
  518.     shl    ax,1
  519. endif
  520.     mov    cs:[CurX],ax
  521.     mov    ax,Y
  522.     mov    cl,_bp cs:[CharSize]
  523.     mul    cl
  524.     mov    cs:[CurY],ax
  525.     pop    ax
  526.     or    al,al            ; was mouse visible?
  527.     jz    @@1
  528.     call    gShowMouse        ; yes - show it at new position
  529. @@1:
  530. ifdef    __use_286__
  531.     pop    ds es
  532.     popa
  533. else
  534.     pop    ds es di si dx cx bx ax
  535. endif
  536. @@Q:
  537.     ret
  538.     ENDP
  539.  
  540.  
  541. gDoneMouse    PROC FAR
  542. ; procedure gDoneMouse; far;
  543. ; resets mouse handler
  544. ARG    doModeFlip : BYTE
  545.  
  546.     cmp    cs:[Active],1
  547.     jnz    @@Q
  548.     cmp    doModeFlip,1
  549.     jnz    @@noflip
  550.     call    mode9bpc
  551. @@noflip:
  552.     push    ax cx si di ds es
  553.     call    gHideMouse        ; hide mouse pointer
  554.     push    cs cs
  555.     pop    ds es
  556.     lsi    SaveBuffer        ; restore character maps
  557.     ldi    C1
  558. ifdef    __use_386__
  559.     mov    cx,16
  560.     cld
  561.     rep    movsd
  562. else
  563.     mov    cx,32
  564.     cld
  565.     rep    movsw
  566. endif
  567.     push    cs:C1C
  568.     push    cs:C2C
  569.     push    cs:C3C
  570.     push    cs:C4C
  571.     call    SaveChars
  572.     mov    ax,0Ch            ; set event handler back to
  573.     mov    cx,OldEvents        ; original
  574.     mov    es,_wp OldHandler
  575.     mov    dx,_wp OldHandler[2]
  576.     int    33h
  577.     pop    es ds di si cx ax
  578. @@Q:
  579.     ret
  580.     ENDP
  581.  
  582.  
  583. gMouseWhereX    PROC FAR
  584. ; function gMouseWhereX : Integer; far;
  585.     mov    ax,cs:[CurX]    ; compute character position from pixel
  586. ifdef    __use_286__
  587.     shr    ax,3
  588. else
  589.     shr    ax,1        ; position
  590.     shr    ax,1
  591.     shr    ax,1
  592. endif
  593.     ret
  594.     ENDP
  595.  
  596. ; function gMouseWhereY : Integer; far;
  597.  
  598. gMouseWhereY    PROC FAR
  599.     push    dx        ; compute character position from pixel
  600.     mov    ax,cs:[CurY]    ; position
  601.     cwd
  602.     div    cs:[CharSize]
  603.     pop    dx
  604.     ret
  605.     ENDP
  606.  
  607. cgModeSet    PROC NEAR
  608. ; program the video adapter so that we can get access to its character
  609. ; generator maps for reading/writing.
  610.  
  611.     push    ds si cx cs
  612.     pop    ds
  613.     lsi    MSData
  614.     mov    cx,2
  615.     mov    dx,3C4h
  616.     cld
  617.     cli
  618. @@L:
  619.     lodsw
  620.     out    dx,ax
  621.     jmp    $+2
  622.     loop    @@L
  623.     mov    dl,0CEh
  624.     mov    cl,3
  625. @@L2:
  626.     lodsw
  627.     out    dx,ax
  628.     jmp    $+2
  629.     loop    @@L2
  630.     pop    cx si ds
  631.     ret
  632.     ENDP
  633.  
  634. MSData:
  635.     DW    0402h        ; CPU writes to map 2
  636.     DW    0704h
  637.     DW    0005h
  638.     DW    0406h        ; map starts at A000:0000 (64K)
  639.     DW    0204h        ; CPU reads from map 2
  640.  
  641. cgModeClear    PROC NEAR
  642. ; reset character generator to display mode.
  643.  
  644.     push    ds cx si cs
  645.     pop    ds
  646.     lsi    MCData
  647.     mov    cx,2
  648.     cld
  649.     cli
  650.     mov    dx,3C4h
  651. @@L1:
  652.     lodsw
  653.     out    dx,ax
  654.     jmp    $+2
  655.     loop    @@L1
  656.     sti
  657.     mov    cl,3
  658.     mov    dl,0CEh
  659. @@L2:
  660.     lodsw
  661.     out    dx,ax
  662.     jmp    $+2
  663.     loop    @@L2
  664.     pop    si cx ds
  665.     ret
  666.     ENDP
  667.  
  668. MCData:
  669.     DW    0302h        ; CPU writes to maps 0 and 1 (0011 mask)
  670.     DW    0304h        ; odd-even addressing
  671.     DW    1005h        ; enable odd-even addressing
  672.     DW    0E06h        ; map starts at B800:0000
  673.     DW    0004h        ; CPU reads from map 0
  674.  
  675.  
  676. LoadChars    PROC NEAR
  677. ARG    Code1,Code2,Code3,Code4
  678. ; load four character maps into C1,C2,C3 and C4
  679.  
  680.     push    ds es cs
  681.     pop    es
  682.     mov    cx,cs:[CharSize]
  683.     shr    cx,1
  684.     mov    ax,0A000h
  685.     mov    ds,ax
  686.     cld
  687.     mov    si,Code1
  688.     ldi    C1
  689.     call    LoadChar
  690.     mov    si,Code2
  691.     ldi    C2
  692.     call    LoadChar
  693.     mov    si,Code3
  694.     ldi    C3
  695.     call    LoadChar
  696.     mov    si,Code4
  697.     ldi    C4
  698.     call    LoadChar
  699.     pop    es ds
  700.     ret
  701.     ENDP
  702.  
  703. SaveChars    PROC NEAR
  704. ARG     Code1,Code2,Code3,Code4
  705. ; copy C1,C2,C3 and C4 into video RAM
  706.     push    ds es cs
  707.     pop    ds
  708.     mov    cx,cs:[CharSize]
  709.     shr    cx,1
  710.     mov    ax,0A000h
  711.     mov    es,ax
  712.     cld
  713.     mov    di,Code1
  714.     lsi    C1
  715.     call    SaveChar
  716.     mov    di,Code2
  717.     lsi    C2
  718.     call    SaveChar
  719.     mov    di,Code3
  720.     lsi    C3
  721.     call    SaveChar
  722.     mov    di,Code4
  723.     lsi    C4
  724.     call    SaveChar
  725.     pop    es ds
  726.     ret
  727.     ENDP
  728.  
  729.  
  730. LoadChar    PROC NEAR
  731. ; es:di -> buffer to fill
  732. ; bx    =  character code
  733.     push    cx
  734.  
  735. ifdef    __use_286__
  736.     shl    si,5
  737. else
  738.     mov    cl,5
  739.     shl    si,cl
  740. endif
  741.     call    MoveChar    ; move CharSize bytes from ds:si -> es:di
  742.     pop    cx
  743.     ret
  744.     ENDP
  745.  
  746. SaveChar    PROC NEAR
  747. ; ds:si -> buffer to put into video RAM
  748. ; bx    =  character code
  749.     push    cx
  750. ifdef    __use_286__
  751.     shl    di,5
  752. else
  753.     mov    cl,5
  754.     shl    di,cl
  755. endif
  756.     call    MoveChar
  757.     pop    cx
  758.     ret
  759.     ENDP
  760.  
  761. MoveChar    PROC NEAR
  762. ; ds:si -> source
  763. ; es:di -> dest
  764.     call    cgModeSet        ; set read/write mode from chargen'r
  765.     rep    movsw
  766.     call    cgModeClear        ; reset normal operation mode
  767.     ret
  768.     ENDP
  769.  
  770.  
  771. UpdateChars    PROC NEAR
  772.     call    computeOffset
  773.     mov    ax,0B800h
  774.     mov    es,ax
  775.     clr    ah
  776.     mov    al,es:[si]        ; get original character maps...
  777.     push    ax
  778.     mov    al,es:[si+2]
  779.     push    ax
  780.     mov    al,es:[si+160]
  781.     push    ax
  782.     mov    al,es:[si+162]
  783.     push    ax
  784.     call    LoadChars
  785.     push    cs            ; ...apply masks on them...
  786.     pop    ds
  787.     mov    cx,CurX
  788.     mov    bx,CurY
  789.     and    cx,7
  790.     mov    ax,CharSize
  791.     dec    ax
  792.     and    bx,ax
  793.     clr    si
  794. @@1:
  795.     cmp    bx,CharSize
  796.     jz    @@2
  797.     mov    ah,_bp C1[bx]
  798.     mov    al,_bp C2[bx]
  799.     mov    dh,_bp ANDMask[si]
  800.     mov    dl,0FFh
  801.     ror    dx,cl
  802.     and    ax,dx
  803.     mov    dh,_bp ORMask[si]
  804.     clr    dl
  805.     shr    dx,cl
  806.     or    ax,dx
  807.     mov    _bp C1[bx],ah
  808.     mov    _bp C2[bx],al
  809.     inc    bx
  810.     inc    si
  811.     cmp    si,CharSize
  812.     jb    @@1
  813.     jmp    @@3
  814. @@2:
  815.     clr    bx
  816. @@4:
  817.     mov    ah,_bp C3[bx]
  818.     mov    al,_bp C4[bx]
  819.     mov    dh,_bp ANDMask[si]
  820.     mov    dl,0FFh
  821.     ror    dx,cl
  822.     and    ax,dx
  823.     mov    dh,_bp ORMask[si]
  824.     clr    dl
  825.     shr    dx,cl
  826.     or    ax,dx
  827.     mov    _bp C3[bx],ah
  828.     mov    _bp C4[bx],al
  829.     inc    bx
  830.     inc    si
  831.     cmp    si,CharSize
  832.     jb    @@4
  833. @@3:
  834.     push    cs:C1C
  835.     push    cs:C2C
  836.     push    cs:C3C
  837.     push    cs:C4C
  838.     call    SaveChars
  839.     ret
  840.     ENDP
  841.  
  842. computeOffset    PROC NEAR
  843. ; returns SI = offset in character buffer of character at (CurX,CurY)
  844.     push    ax bx dx
  845.     mov    si,cs:[CurX]
  846. ifdef    __use_286__
  847.     shr    si,2
  848. else
  849.     shr    si,1
  850.     shr    si,1
  851. endif
  852.     mov    ax,cs:[CurY]
  853.     cwd
  854.     mov    bx,cs:[CharSize]
  855.     div    bx
  856.     mov    bl,160
  857.     mul    bl
  858.     add    si,ax
  859.     and    si,0FFFEh    ; we need character, not attibute
  860.     pop    dx bx ax
  861.     ret
  862.     ENDP
  863.  
  864. GetNewPos    PROC NEAR
  865.     mov    ax,0Bh        ; query last mouse motion
  866.     int    33h
  867.     add    cs:[CurX],cx    ; we don't convert mickeys to pixels, we
  868.     add    cs:[CurY],dx    ; just treat mickey counts as pixel counts
  869.     mov    ax,cs:[CurX]
  870.     or    ax,ax        ; check screen boundaries
  871.     js    @@6
  872.     cmp    ax,cs:[XMin]
  873.     jae    @@1
  874. @@6:
  875.     clr    ax
  876.     jmp    @@2
  877. @@1:
  878.     cmp    ax,638
  879.     jb    @@2
  880.     mov    ax,638
  881. @@2:
  882.     mov    cs:[CurX],ax
  883.     mov    ax,cs:[CurY]
  884.     or    ax,ax
  885.     js    @@5
  886.     cmp    ax,cs:[YMin]
  887.     jae    @@3
  888. @@5:
  889.     clr    ax
  890.     jmp    @@4
  891. @@3:
  892.     cmp    ax,cs:[YSize]
  893.     jb    @@4
  894.     mov    ax,cs:[YSize]
  895. @@4:
  896.     mov    cs:[CurY],ax
  897.     ret
  898.     ENDP
  899.  
  900. isVGA    proc
  901.     mov    ax,1A00h
  902.     int    10h
  903.     cmp    al,1Ah
  904.     ret
  905.     ENDP
  906.  
  907. checkVideo    PROC NEAR
  908.     call    isVGA
  909.     jz    @@Ok        ; VGA
  910.     push    es
  911.     mov    ax,40h
  912.     mov    es,ax
  913.     mov    al,es:[87h]
  914.     pop    es
  915.     or    al,al
  916.     jz    @@Fail        ; not EGA
  917.     mov    cs:[CharSize],14
  918.     mov    cs:[YSize],344    ; ScreenHeightPix - 1
  919.     mov    cs:[YMax],344
  920. @@Ok:
  921.     mov    ah,0Fh
  922.     int    10h
  923.     cmp    al,3        ; 80x25 text mode?
  924.     jnz    @@Fail        ; we won't operate in any other mode
  925.     clc
  926.     ret
  927. @@Fail:
  928.     stc
  929.     ret
  930.     ENDP
  931.  
  932. i33h:
  933.     push    ax
  934.     mov    ah,0Fh
  935.     int    10h
  936.     cmp    al,3        ; video mode 3?
  937.     pop    ax
  938.     jnz    @@JOld        ; we do not operating in any other modes
  939.     cmp    cs:[Active],0
  940.     jz    @@JOld        ; we're not active
  941.     cmp    ax,1        ; show mouse pointer
  942.     jz    @@1
  943.     cmp    ax,2        ; hide mouse pointer
  944.     jz    @@2
  945.     cmp    ax,3        ; get mouse position and button count
  946.     jz    @@3
  947.     cmp    ax,4        ; move mouse pointer
  948.     jz    @@4
  949.     cmp    ax,7        ; set horizontal range
  950.     jz    @@7
  951.     cmp    ax,8        ; set vertical range
  952.     jz    @@8
  953.     cmp    ax,0Ch        ; set new handler
  954.     jz    @@0C
  955.     cmp    ax,14h        ; exchange handlers
  956.     jz    @@14
  957. @@JOld:
  958.     db    0EAh        ; jump to previous handler
  959. Save33    dd    0
  960. @@1:                ; show mouse
  961.     call    gShowMouse
  962.     iret
  963. @@2:                ; hide mouse
  964.     call    gHideMouse
  965.     iret
  966. @@3:                ; get mouse position and button count
  967.     pushf
  968.     callf    cs:[Save33]
  969.     push    ax        ; replace CX,DX with our virtual
  970.     mov    ax,cs:[CurY]    ; coordinates
  971.     cwd
  972.     div    cs:[CharSize]
  973. ifdef    __use_286__
  974.     shl    ax,3
  975. else
  976.     shl    ax,1
  977.     shl    ax,1
  978.     shl    ax,1
  979. endif
  980.     mov    cx,cs:[CurX]
  981.     mov    dx,ax
  982.     and    cl,0F8h
  983.     and    dl,0F8h
  984.     pop    ax
  985.     iret
  986. @@4:                ; move pointer
  987.     mov    cs:[CurX],cx
  988.     push    dx
  989. ifdef    __use_286__
  990.     shr    dx,3
  991. else
  992.     shr    dx,1
  993.     shr    dx,1
  994.     shr    dx,1
  995. endif
  996.     push    ax
  997.     mov    ax,dx
  998.     mul    _bp cs:[CharSize]
  999.     mov    cs:[CurY],ax
  1000.     pop    ax
  1001.     pop    dx
  1002.     iret
  1003. @@7:                ; set horizontal range
  1004.     mov    cs:[XMin],cx
  1005.     mov    cs:[XSize],dx
  1006.     iret
  1007. @@8:                ; set vertical range
  1008.     push    ax
  1009.     mov    ax,cx
  1010. ifdef    __use_286__
  1011.     shr    ax,3
  1012. else
  1013.     shr    ax,1
  1014.     shr    ax,1
  1015.     shr    ax,1
  1016. endif
  1017.     mul    _bp cs:[CharSize]
  1018.     mov    cs:[YMin],ax
  1019.     mov    ax,dx
  1020. ifdef    __use_286__
  1021.     shr    ax,3
  1022. else
  1023.     shr    ax,1
  1024.     shr    ax,1
  1025.     shr    ax,1
  1026. endif
  1027.     mul    _bp cs:[CharSize]
  1028.     cmp    ax,cs:[YMax]
  1029.     jae    @@81
  1030.     mov    cs:[YSize],ax
  1031. @@81:
  1032.     pop    ax
  1033.     iret
  1034. @@0C:                ; set new handler
  1035.     mov    _wp cs:[OldEvents],cx
  1036.     mov    _wp cs:[OldHandler],dx
  1037.     mov    _wp cs:[OldHandler][2],es
  1038.     iret
  1039. @@14:                ; exchange handlers
  1040.     push    ax
  1041.     xchg    cx,cs:[OldEvents]
  1042.     xchg    _wp cs:[OldHandler],dx
  1043.     mov    ax,es
  1044.     xchg    _wp cs:[OldHandler][2],ax
  1045.     mov    es,ax
  1046.     pop    ax
  1047.     iret
  1048.  
  1049. Intercept33    PROC FAR
  1050.     cmp    cs:[Active],1
  1051.     jnz    @@Q
  1052.     push    ds
  1053.     clr    ax
  1054.     mov    ds,ax
  1055.     mov    si,33h*4
  1056.     push    cs
  1057.     pop    es
  1058.     ldi    Save33
  1059.     cld
  1060. ifdef    __use_386__
  1061.     movsd
  1062. else
  1063.     movsw
  1064.     movsw
  1065. endif
  1066.     push    ds
  1067.     pop    es
  1068.     mov    di,33h*4
  1069.     load    ax,i33h
  1070.     cli
  1071.     stosw
  1072.     mov    ax,cs
  1073.     stosw
  1074.     sti
  1075.     pop    ds
  1076. @@Q:
  1077.     ret
  1078.     ENDP
  1079.  
  1080. Untercept33    PROC FAR
  1081.     mov    ax,_wp cs:[Save33]
  1082.     or    ax,_wp cs:[Save33][2]
  1083.     jz    @@Q
  1084.     push    ds
  1085.     clr    ax
  1086.     mov    es,ax
  1087.     mov    di,33h*4
  1088.     push    cs
  1089.     pop    ds
  1090.     lsi    Save33
  1091.     cld
  1092.     cli
  1093. ifdef    __use_386__
  1094.     movsd
  1095. else
  1096.     movsw
  1097.     movsw
  1098.     sti
  1099.     pop    ds
  1100. endif
  1101. @@Q:
  1102.     ret
  1103.     ENDP
  1104.  
  1105. mode8bpc    PROC    NEAR
  1106. ; sets 8x16 character matrix mode on VGAs
  1107.  
  1108.     call    isVGA
  1109.     jnz    @@noflip
  1110.     cli
  1111.     mov    dx,3C4h        ; sequencer
  1112.     mov    al,1
  1113.     out    dx,al        ; clocking mode 3c5(1)
  1114.     inc    dx
  1115.     in    al,dx        ; clocking value
  1116.     or    al,1        ; set 8 dots/char
  1117.  
  1118.     out    dx,al        ; write value
  1119.     mov    dx,3CCh        ; miscellaneous register ( read )
  1120.     in    al,dx
  1121.     and    al,0F3h         ; 14 MHz ( 8 dots )
  1122.  
  1123.     mov    dx,3C2h        ; miscellaneous register ( write )
  1124.     out    dx,al
  1125.     mov    dx,3DAh        ; force address mode
  1126.     in    al,dx
  1127.     mov    dx,3C0h        ; Attribute controller
  1128.     mov    al,13h        ; horizontal pixel panning
  1129.     out    dx,al
  1130.     clr    al        ; shift data left = 0
  1131.     out    dx,al
  1132.     mov    al,20h          ; set bit 5 to 1 ( enable display )
  1133.     out    dx,al
  1134.     sti
  1135.     mov    _bp cs:[C1C],1
  1136.     mov    _bp cs:[C2C],2
  1137.     mov    _bp cs:[C3C],3
  1138.     mov    _bp cs:[C4C],4
  1139. @@noflip:
  1140.     ret
  1141.     ENDP
  1142.  
  1143. mode9bpc    PROC    NEAR
  1144. ; sets 9x16 character matrix mode on VGAs
  1145.  
  1146.     call    isVGA
  1147.     jnz    @@noflip
  1148.     cli
  1149.     mov    dx,3C4h        ; sequencer
  1150.     mov    al,1
  1151.     out    dx,al        ; clocking mode 3c5(1)
  1152.     inc    dx
  1153.     in    al,dx        ; clocking value
  1154.     and    al,0FEh        ; set 9 dots/char
  1155.     out    dx,al        ; write value
  1156.     mov    dx,3CCh        ; miscellaneous register ( read )
  1157.     in    al,dx
  1158.     and    al,0F3h
  1159.     or    al,4        ; 16 Mhz ( 9 dots )
  1160.     mov    dx,3C2h        ; miscellaneous register ( write )
  1161.     out    dx,al
  1162.     mov    dx,3DAh        ; force address mode
  1163.     in    al,dx
  1164.     mov    dx,3C0h        ; Attribute controller
  1165.     mov    al,13h        ; horizontal pixel panning
  1166.     out    dx,al
  1167.     clr    al        ; shift data left = -1
  1168.     dec    al
  1169.     out    dx,al
  1170.     mov    al,20h          ; set bit 5 to 1 ( enable display )
  1171.     out    dx,al
  1172.     sti
  1173. @@noflip:
  1174.     ret
  1175.     ENDP
  1176.  
  1177. gMouseActive    PROC    FAR
  1178. ; returns Boolean flag indicating that gMouse event handler is currently active
  1179.  
  1180.     mov    al,cs:[Active]
  1181.     ret
  1182.     ENDP
  1183.  
  1184.  
  1185. gMouseSetChars    PROC    FAR
  1186. ; procedure gMouseSetChars( C1, C2, C3, C4 : Char ); far;
  1187. ARG    Code1 : BYTE, Code2 : BYTE, Code3 : BYTE, Code4 : BYTE
  1188.  
  1189.     mov    al,Code1
  1190.     mov    cs:C1C,ax
  1191.     mov    al,Code2
  1192.     mov    cs:C2C,ax
  1193.     mov    al,Code3
  1194.     mov    cs:C2C,ax
  1195.     mov    al,Code4
  1196.     mov    cs:C4C,ax
  1197.     ret
  1198.     ENDP
  1199.  
  1200. gMouseGetChars    PROC     FAR
  1201. ; procedure gMouseGetChars( var C1, C2, C3, C4 : Char ); far;
  1202. ARG    Code1 : DWORD, Code2 : DWORD, Code3 : DWORD, Code4 : DWORD
  1203.  
  1204.     mov    ax,cs:C1C
  1205.     les    di,Code1
  1206.     stosb
  1207.     mov    ax,cs:C2C
  1208.     les    di,Code2
  1209.     stosb
  1210.     mov    ax,cs:C3C
  1211.     les    di,Code3
  1212.     stosb
  1213.     mov    ax,cs:C4C
  1214.     les    di,Code4
  1215.     stosb
  1216.     ret
  1217.     ENDP
  1218.  
  1219. ; that's all, folks!
  1220.  
  1221.     END
  1222.